#include "StdAfx.h"


Reader::Reader()
{
}
Reader::Reader(string file_name)
{
	LoadFile(file_name);
}
Reader::~Reader(void)
{
}
void Reader::SetRegex(std::string exp)
{
	if(lastRegex!=exp)
	{
		Regex.assign(exp.begin(), exp.end());
		lastRegex=exp;
	}
	Flags=boost::match_default;
}
void Reader::LoadFile(string file_name)
{
	FileName=file_name;
	File=ReadFile(file_name)+"[eof]";
	CurPos=File.begin();
}
std::string Reader::ReadFile(string file_name)
{
	std::string tmp=(std::string)file_name;
	std::ifstream fileStream(tmp);
	if(!fileStream.is_open())
		throw BException("Stream: Could not open "<<file_name);
	File="";
	while(!fileStream.eof())
	{
		std::getline(fileStream, tmp);
		File+=tmp+"\n";
	}
	return File;
}
Reader::strVector Reader::Parse(std::string &str, std::string exp_str)
{
	strVector vec;
	//init the regex vars
	SetRegex(exp_str);
	std::string::const_iterator start=str.begin(), end=str.end();
	//parse the string
	while(boost::regex_search(start, end, Matches, Regex, Flags))
	{
		//store the results in the vector
		for(unsigned int i=1;i<Matches.size();i++)
			vec.push_back(std::string(Matches[i].first, Matches[i].second));
		//advance the iterator
		start = Matches[0].second; 
		// update Flags: 
		Flags |= boost::match_prev_avail; 
		Flags |= boost::match_not_bob;
	}
	return vec;
}
bool Reader::eof()
{
	return CurPos==File.end();
}
std::string::const_iterator Reader::GetItBefore(std::string str)
{
	return GetNextOccurence(str).first;
}
std::string::const_iterator Reader::GetItAfter(std::string str)
{
	return GetNextOccurence(str).second;
}
Reader::itPair Reader::GetNextOccurence(std::string str)
{
	//init the regex vars
	SetRegex("("+str+")");
	std::string::const_iterator start=CurPos, end=File.end();
	//find the string
	itPair pair;
	if(boost::regex_search(start, end, Matches, Regex, Flags))
	{
		pair.first=Matches[0].first;
		pair.second=Matches[0].second;
	}
	else pair.first=pair.second=File.end();
	return pair;
}
string Reader::GetNext()
{
	string str;
	std::string::const_iterator start=CurPos, end=File.end();
	if(boost::regex_search(start, end, Matches, Regex, Flags))
	{
		start=Matches[0].second;
		str=std::string(Matches[1].first, Matches[1].second);
	}
	CurPos=start;
	return str;
}
bool Reader::JumpAfterNext(std::string str)
{
	std::string::const_iterator nextPos=GetItAfter(str);
	if(nextPos!=File.end())
	{
		CurPos=nextPos;
		return true;
	}
	else return false;
}
void Reader::SetGetRealRegex()
{
	SetRegex("(\\-?[\\d]+\\.\\d*)");
}
Vec3 Reader::GetVec3()
{
	Vec3 v;
	SetGetRealRegex();
	v.x=string::alphaToReal(GetNext());
	v.y=string::alphaToReal(GetNext());
	v.z=string::alphaToReal(GetNext());
	return v;
}
int Reader::GetInt()
{
	//init the regex vars
	SetRegex("(\\d+)");
	return string::alphaToInt(GetNext());
}
real Reader::GetReal()
{
	//init the regex vars
	SetGetRealRegex();
	return string::alphaToReal(GetNext());
}
string Reader::GetQuotedString()
{
	//init the regex vars
	SetRegex("\"(.*?)\"");
	return GetNext();
}
string Reader::GetToken()
{
	SetRegex("(\\w+)");
	return GetNext();
}
void Reader::Reset()
{
	CurPos=File.begin();
}
string Reader::GetNext(string strid)
{
	if(JumpAfterNext(strid))
		return GetToken();
	else _log("Expected '"<<strid<<"' in "<<FileName<<" not found.");
	return string();
}
sptr<GameResource> Reader::GetResc(string strid)
{
	sptr<GameResource> resc; 
	if(JumpAfterNext(strid))
	{
		string str=GetToken();
		resc=_RESC(str);
	}
	return resc;
}
Reader::strVector Reader::TokenizeSTD(std::string &str)
{
	return Parse(str, "([\\w|\\-|\\.]+|[\"|\\{|\\}])");
}
Reader::strPairVector Reader::ParseIntoPairs(std::string str)
{
	strPairVector vec;
	strVector strVec=Parse(str, "([+|\\-|;])([\\w|\\.|=|\\/|\\\\]*)");
	for(unsigned int i=0;i<strVec.size()-1;i+=2)
		vec.push_back(strPair(strVec[i], strVec[i+1]));
	return vec;
}
sptr<Binding> Reader::ParseIntoBinding(std::string str)
{
	sptr<Binding> binding=sptr<Binding>(new Binding());
	strVector strVec=Parse(str, "(.*)=(.*)");
	if(strVec.size())
	{
		binding->Name=strVec[0];
		binding->Aux=strVec[1];
	}
	return binding;
}
BBVector<sptr<Binding>> Reader::GetBindings(string ident)
{
	//initialize variables
	BBVector<sptr<Binding>> vec;
	vec.Name=FileName<<" | ["<<ident<<"]";
	strPairVector pairs;
	strVector strVec=Parse(File, "\\["<<ident<<"\\](.*?)\\[.*\\]");
	if(strVec.size())
	{
		pairs=ParseIntoPairs(strVec[0]);
		for(unsigned int i=0;i<pairs.size();i++)
		{
			if(pairs[i].first=="+")
			{
				sptr<Binding> binding=ParseIntoBinding(pairs[i].second);
				vec.push_back(binding);
			}
			else if(pairs[i].first=="-")
				try
				{
					sptr<Binding> binding=ParseIntoBinding(pairs[i].second);
					vec.remove(binding->Name);
				}
				catch(BException&)
				{
				}
		}
	}
	return vec;
}
